home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 9 / Night Owl CD-ROM (NOPV9) (Night Owl Publisher) (1993).ISO / 050a / _tsgrep.zip / TSGREP.S < prev   
Text File  |  1993-05-04  |  61KB  |  1,626 lines

  1. /**************************************************************************
  2.            TSGREP ... A regular expression line extractor, v4.5
  3.  **************************************************************************/
  4.  
  5. /**************************************************************************
  6.           Forward Proc Declarations
  7.  **************************************************************************/
  8.  
  9. forward INTEGER proc multiple_filespecs      // loads files separated by ^
  10.     (VAR STRING filespec)
  11.  
  12. forward proc loadfileList()                  // loads list of files
  13.                                              // from  @file
  14. forward proc nextfile_if_NOT_excluded()      // loads file if NOT on
  15.                                              // excluded extension list
  16. forward proc load_recursively                // loads files from all sub-
  17.      (STRING arg)                            // directories below current
  18. forward proc check_for_abort()               // aborts between file loads
  19.                                              // if <escape>
  20. forward proc end_processing                  // cleanup AND view
  21.      (INTEGER MODE)
  22.  
  23. forward proc interactive_setUp()             // Setup for interactive
  24.                                              // operation
  25. forward INTEGER proc ask_input()             // Displays help; asks inputs
  26.  
  27. forward proc reload_files()                  // interactive mode : reload files
  28.  
  29. forward proc keystroke_help()                // show legal keystrokes
  30.  
  31. forward proc process_AND()                   // processes -and- in search STRING
  32.  
  33. forward proc make_other_hit_lists()           // for use by ...
  34.  
  35. forward proc toggle_hits()                   //  toggles display of hit lines
  36.  
  37. forward proc goto_hit_List(INTEGER MODE)     // goes to outfile
  38.  
  39. forward proc remove_file_from_hit_List()     // removes a file & hits
  40.  
  41. forward proc undo_all_removes ()             // undoes removes
  42.  
  43. forward proc gotohit()                       // goes to another file
  44.                                              // from outfile
  45. /*
  46. forward STRING proc repl_char                // replaces chars in a STRING
  47.     (STRING find_string,
  48.      STRING repl_string,
  49.      VAR STRING target)
  50. */
  51. string proc repl_char(STRING find_string, STRING repl_string, VAR STRING target)
  52.      while Pos(find_string, target)
  53.           target = SubStr(target,
  54.                           1,
  55.                           Pos(find_string, target)-1
  56.                           ) +
  57.                     repl_string +
  58.                     SubStr(target,
  59.                            Pos(find_string, target)+
  60.                                Length(find_string),
  61.                            Length(target)
  62.                            )
  63.      endwhile
  64.      return(target)
  65. end
  66.  
  67.  
  68. forward proc hilite()                        // highlights text
  69.  
  70. forward proc unload()                        // unloads TSGREP.
  71.  
  72. /**************************************************************************
  73.           Variable & CONSTANT Declarations
  74.  **************************************************************************/
  75. CONSTANT
  76.      interactive = 1,
  77.      cmdline = 0,
  78.      maxfn = 60,                        // :U: largest file name TSGREP can handle
  79.      maxspec = 120                      // :U: largest input file spec
  80.  
  81. INTEGER
  82.      normal_Attr,                       // Attribute for normal text
  83.      hilite_Attr,                       // Attribute for highlighting
  84.                                         // (change these at the beginnig of
  85.                                         // Main(), NOT here.)
  86.      query_saves = TRUE,                // :U: whether to query saves (interactive)
  87.      sgrepmode = cmdline,               // initial mode
  88.      done_executed_once = FALSE,        // for determining non-interactive
  89.      cid = 0,                           // first file loaded
  90.      oid = 0,                           // buffer to become output file
  91.      copy_of_list,                      // id for copy of above
  92.      files_only,                        // id for copy with only files
  93.      cfid = 0,                          // id for buffer with current files
  94.      id = 0,                            // id of file being processed
  95.      tid = 0,                           // a temp buffer used for
  96.                                         // searchstring processing
  97.      load_file =  TRUE,                 // load outfile into editor
  98.      linenumbers = TRUE,                // to include (OR NOT)
  99.      hits = 0,                          // hits counter
  100.      write_hits_flag = TRUE,            // write hits in outfile
  101.      no_hitters_flag = FALSE,           // were there any?
  102.      curr_file_hits = 0,                // hits counter
  103.      name_line,                         // line filename placed on
  104.      files = 0,                         // file counter
  105.      lndigits = 5,                      // :U: max digits in a line number
  106.      linenumber = 0,                    // line number of find
  107.      auto,                              // original AutoIndent state
  108.      msgs,                              // original msg level state
  109.      wild,                              // original loadwild state
  110.      im  ,                              // original insert state
  111.      km  ,                              // original killbuffmax state
  112.      col = 1,                           // for gotohit
  113.      first_file_line = 12,              // for gotohit
  114.      isloaded = 0,                      // for restoring curr files
  115.      sstring_hist_buff = 0,             // history buffers for Ask()s
  116.      infile_hist_buff = 0,
  117.      options_hist_buff = 0,
  118.      outfile_hist_buff = 0,
  119.      getting_dirs_line =     9,          // display lines
  120.      loading_files_line =    9,
  121.      getting_files_line =    9,
  122.      processing_line =       9,
  123.      files_loaded_line =    10,
  124.      files_processed_line = 10,
  125.      dirs_found_line =      10,
  126.      hits_line =            11,
  127.      press_any_key_line =   11
  128.  
  129. STRING
  130.      v[3]= '4.6',                       // :U: TSGREP version
  131.      ramdrive[3] = '',                  // :U: format:  'd:\'  OR '\'
  132.      dir_spec[2] = '*.',                // :U: change to '' if you use directories
  133.                                         //     with an extension as part of name
  134.      pad[60] = ' ───────────────────────────────────────────────────────────',
  135.      name[maxfn] = '',                  // name of file being processed
  136.      name_prefix[4] = ' ',           // :U: inserted into outfile before name
  137.      name_prefix_re[SizeOf(name_prefix)*2],
  138.                                         // version of above with, double length
  139.      name_suffix[1] = ':',              // :U: inserted into outfile after name
  140.      options[25]  ='',                  // search option, sgrep options
  141.      infile[maxspec]  ='',              // filespec for input
  142.      outfile[maxfn]  ='',               // filespec for output
  143.      sstring[255] ='',                  // search STRING
  144.      default_name[maxfn] ="TSGREP.TMP",  // :U:default for above
  145.      default_name_2[maxfn] ="TSGREP.$MP",// :U:filespec for files-only list
  146.      OR_operator[4] = '-or-',           // :U: represents | in searchstring
  147.      AND_operator[5] = '-and-',         // :U: represents AND in searchstring
  148.      eq_char[2] = '\-',                 // :U: represents = in searchstring
  149.      space_char[1] = '_',               // :U: represents   in searchstring
  150.      less_than[2] = '[[',               // :U: represents < in searchstring
  151.      greater_than[2] = ']]',            // :U: represents > in searchstring
  152.      one_hit_flag[2] = '\1',            // :U: flag for stop after 1 hit
  153.      dont_write_hits[2] = '\w',         // :U: flag for NOT writing hits in outfile
  154.      no_line_numbers[2] = '\#',         // :U: flag for NOT writing hits in outfile
  155.      dont_decode_spacechar[2] = '\_',   // :U: flag for NOT decoding space_char
  156.      dont_load_outfile[2] = '\l',       // :U: flag for NOT loading output file
  157.      no_re_flag[2] = '\x',              // :U: flag for disable auto regexp mode
  158.      file_sep_char[1] = '^',            // :U: file separator character
  159.      recurse_flag[1] = '+' ,            // :U: recursive search indicator
  160.      list_file_flag[1] = '@' ,          // :U: list file flag
  161.      line[255] = ''                     //  used variously
  162.  
  163. /**************************************************************************
  164.           KEY DEFINITIONS
  165.  **************************************************************************/
  166.  
  167. keydef file
  168.      <alt enter>    Disable(file) goto_hit_List(1)
  169.                     BegLine() UpdateDisplay() Find(sstring, options)
  170.      <ctrl enter>    Disable(file) goto_hit_List(1)
  171.                     BegLine() UpdateDisplay() Find(sstring, options)
  172.      <alt escape>   if sgrepmode == cmdline Exit() endif
  173.      <alt n>        Find(sstring, options + '+')
  174.      <alt p>        Find(sstring, options + 'b')
  175.      <alt h>        keystroke_help()
  176.      <alt ->        unload()
  177. end
  178.  
  179. keydef hit_file
  180.      <alt enter>    Disable(hit_file) gotohit()
  181.                     BegLine() UpdateDisplay() Find(sstring, options)
  182.      <ctrl enter>    Disable(hit_file) gotohit()
  183.                     BegLine() UpdateDisplay() Find(sstring, options)
  184.      <alt escape>   if sgrepmode == cmdline
  185.                     GotoBufferId(oid) SaveFile() Exit() endif
  186.      <alt r>        remove_file_from_hit_List()
  187.      <alt u>        undo_all_removes()
  188.      <alt f>        toggle_hits()
  189.      <alt n>        if Find(name_prefix, '^+')  hilite() endif
  190.      <alt p>        if Find(name_prefix, '^b') hilite() endif
  191.      <alt h>        keystroke_help()
  192.      <alt ->        unload()
  193. end
  194.  
  195. /**************************************************************************
  196.           PROCEDURES
  197.  **************************************************************************/
  198. /*
  199. proc viewfile()
  200.      string fn[32]='',
  201.             saved_wordset[32]= Set(wordset,chrset('a-zA-Z0-9!.\\:-'))
  202.      set(break,on)
  203.      pushposition()
  204.      pushblock()
  205.      if MarkWord()
  206.           fn = GetText(Query(BlockBegCol),
  207.                        Query(BlockEndCol) - Query(BlockBegCol) + 1)
  208.           if fileexists(fn)
  209.                addhistorystr(fn, _edit_history_)
  210.                popposition()
  211.                editfile(fn)
  212.                if NOT List(currfilename(), 80)
  213.                     abandonfile()
  214.                     goto endit
  215.                endif
  216.           elseif fileexists('i:\usr\' + fn)
  217.                addhistorystr('i:\usr\' + fn, _edit_history_)
  218.                popposition()
  219.                editfile('i:\usr\' + fn)
  220.                if NOT List(currfilename(), 80)
  221.                     abandonfile()
  222.                     goto endit
  223.                endif
  224.           else
  225.                addhistorystr(fn, _edit_history_)
  226.                message("can't find ", fn)
  227.                popposition()
  228.                editfile(fn)
  229.                if numlines() and NOT List(currfilename(), 80)
  230.                     abandonfile()
  231.                     goto endit
  232.                else
  233. //               autoexec
  234.                     abandonfile()
  235.                     updatedisplay(_STATUSLINE_REFRESH_)
  236.                     If not YesNo('Create '+ fn + '?') == 1
  237.                          editfile(fn)
  238.                     endif
  239.                endif
  240.           endif
  241.      else
  242.           popposition()
  243.      endif
  244. endit:
  245.      set(break,OFF)
  246.      popblock()
  247.      Set(wordset,saved_wordset)
  248.      updatedisplay()
  249. end
  250.  
  251. <alt e> viewfile()
  252.  
  253. proc whenloaded()
  254.      viewfile()
  255. end
  256.  
  257. */
  258. proc MAIN()
  259.      normal_Attr = Query(TextAttr)           // Attribute for normal text
  260.      hilite_Attr = Query(HiLiteAttr)         // Attribute for highlighting
  261.      hits = 0                                // balls = 2
  262.      files = 0                               // runs =  0 <g>
  263.      load_file =  TRUE                       // :U: load outfile into editor
  264.      linenumbers = TRUE                      // :U: to include (OR NOT)
  265.      write_hits_flag = TRUE                  // :U: write hits in outfile
  266.  
  267.      if sstring_hist_buff == 0               // set up histories for Asks
  268.         sstring_hist_buff = GetFreeHistory()
  269.          infile_hist_buff = GetFreeHistory()
  270.         options_hist_buff = GetFreeHistory()
  271.         outfile_hist_buff = GetFreeHistory()
  272.         AddHistoryStr(default_name, outfile_hist_buff)
  273.         AddHistoryStr('i',  options_hist_buff)
  274.      endif
  275.  
  276.  
  277.      if NOT done_executed_once               // don't get after 1st time
  278.           options = GetEnvStr('OPTIONS')
  279.                AddHistoryStr(options, options_hist_buff)
  280.           infile  = GetEnvStr('INFILE')
  281.                AddHistoryStr(infile, infile_hist_buff)
  282.           Lower(infile)
  283.           outfile = GetEnvStr('OUTFILE')
  284.                AddHistoryStr(outfile, outfile_hist_buff)
  285.           sstring = GetEnvStr('STRING')
  286.                AddHistoryStr(sstring, sstring_hist_buff)
  287.      endif
  288.  
  289.      /*
  290.           if no Env STRINGs, go interactive
  291.      */
  292.      if (sstring == '') OR done_executed_once       // tests whether running
  293.           sgrepmode = interactive                 // from cmdline
  294.           interactive_setUp()
  295.      endif
  296.  
  297.      /*
  298.           Set editor states
  299.      */
  300.  
  301.      Set(Break, ON)
  302.      im   = Set(Insert,ON)
  303.      auto = Set(AutoIndent,OFF)
  304. //   msgs = Set(MsgLevel,_NONE_)
  305. //   msgs = Set(MsgLevel,_ALL_MESSAGES_)
  306.      msgs = Set(MsgLevel,_warnings_only_)
  307.      wild = Set(LoadWildFromInside, ON)
  308.      km   = Set(KillMax, 0)
  309.  
  310.      /*
  311.         The two lines below are unique for my setup only all my
  312.         when(event) macros check this variable. if TRUE, they do no
  313.         processing. This prevents any states from being set that I don't
  314.         want, e.g., AutoIndent.
  315.      */
  316.      SetGlobalInt('Bypass_WhenSwitchToFile', TRUE)
  317.      SetGlobalInt('Bypass_WhenFirstEdited', TRUE)
  318.  
  319.      /*
  320.      Set environment.
  321.      Parse option string AND set flags.
  322.      */
  323.      if oid                        // to ensure minimal # of buffers
  324.           AbandonFile(oid)
  325.      endif
  326.      oid = CreateTempBuffer()      // buffer to become output file
  327.  
  328.      if Length(options) == 0                 // set default options
  329.           options = 'i'
  330.      else
  331.           /*
  332.                Set 'don't write lines' flag
  333.           */
  334.           if Pos(dont_write_hits, options)
  335.                options = repl_char(dont_write_hits, '', options) // get rid of option
  336.                write_hits_flag = FALSE
  337.                if NOT Pos(one_hit_flag, options)     // set 'one hit' mode
  338.                     options = options + one_hit_flag
  339.                endif
  340.           endif
  341.  
  342.           /*
  343.                Set flag for loading the output file
  344.           */
  345.           if Pos(dont_load_outfile, options)
  346.                load_file = FALSE             // strip from options
  347.                options = repl_char(dont_load_outfile, '', options)
  348.           endif
  349.  
  350.           /*
  351.                Set flag for line number suppression
  352.           */
  353.           if Pos(no_line_numbers, options)
  354.                linenumbers = FALSE          // strip from options
  355.                options = repl_char(no_line_numbers, '', options)
  356.           endif
  357.      endif
  358.  
  359.      /*
  360.           Set reg exp mode if certain STRINGs in search STRING,
  361.           unless no_re_flag option used.
  362.      */
  363.      line = sstring                          // to preserve state
  364.      Lower(sstring)
  365.      Lower(OR_operator)                      // in case someone defines
  366.      if (Pos (OR_operator, sstring) OR       // variable with upper case
  367.          Pos(AND_operator, sstring) OR
  368.          Pos(".*",        sstring) OR
  369.          Pos("[" ,        sstring)
  370.         )  AND
  371.         NOT Pos(no_re_flag, options) AND     // if NOT overridden
  372.         NOT Pos('x', options)                // if NOT present
  373.         options = options + 'x'
  374.      endif                                   // then
  375.      if Pos(no_re_flag, options)             // strip out no_re_flag
  376.           options = repl_char(no_re_flag, '', options)
  377.      endif
  378.      sstring = line                          // to restore state
  379.  
  380.      /*
  381.           Get rid of unusable options.
  382.      */
  383.      if Pos('g', options)
  384.           options = repl_char('g', '', options)
  385.      endif
  386.      if Pos('b', options)              // get rid of option we can't use
  387.           options = repl_char('b', '', options)
  388.      endif
  389.      if Pos('+', options)              // get rid of option we can't use
  390.           options = repl_char('+', '', options)
  391.      endif
  392.      if Pos('l', options)              // get rid of option we can't use
  393.           options = repl_char('l', '', options)
  394.      endif
  395.  
  396.      /*
  397.      Decode Searchstring
  398.  
  399.           Substitute < for less_than
  400.           Substitute > for greater_than
  401.      */
  402.      sstring = repl_char(less_than, '<', sstring)
  403.      sstring = repl_char(greater_than, '>', sstring)
  404.      /*
  405.           Substitute | for OR_operator
  406.      */
  407.      if Pos('x', options)                    // regexp only
  408.           sstring = repl_char(OR_operator, '|', sstring)
  409.      endif
  410.      /*
  411.           Substitute | for OR_operator
  412.      */
  413.      if Pos('x', options)                    // regexp only
  414.           sstring = repl_char(OR_operator, '|', sstring)
  415.      endif
  416.  
  417.  
  418.      /*
  419.           Substitute = for eq_char
  420.      */
  421.  
  422.      sstring = repl_char(eq_char, '=', sstring) // decode equal signs
  423.  
  424.      /*
  425.           Set up AND
  426.      */
  427.      if Pos(AND_operator, sstring)
  428.           process_AND()
  429.      endif
  430.  
  431.      /*
  432.           Substitute spaces for space char
  433.      */
  434.      if NOT Pos(dont_decode_spacechar, options)               // decode spaces
  435.           sstring = repl_char(space_char,  ' ', sstring)
  436.      else
  437.           options = repl_char(dont_decode_spacechar, '', options)
  438.      endif
  439.  
  440. /*
  441.      Provide Default Braces if | is used with regular expr.
  442. */
  443.      if Pos('|', sstring) AND Pos('x', options)
  444.           tid = CreateTempBuffer()
  445.           InsertText(sstring)                // put STRING in buffer
  446.           BegFile()
  447.           while lfind ('[\}]\|\c[~\{]', 'gx') // process {...}|...
  448.                InsertText('{')               // becomes {...}|{...}
  449.                EndLine()
  450.                InsertText('}')
  451.           endwhile
  452.           while lfind ('[~\}]\c\|[\{]', 'gx')// process ...|{...}
  453.                InsertText('}')               // becomes {...}|{...}
  454.                BegLine()
  455.                InsertText('{')
  456.           endwhile
  457.           if lfind ('[~\}]\|[~\{]', 'x')     // process ...|...
  458.              Replace('{[~\}]}{\|}{[~\{]}', '\1}\2{\3', 'gnx')
  459.              BegLine()                       // becomes {...}|{...}
  460.              InsertText('{')
  461.              EndLine()
  462.              InsertText('}')
  463.           else
  464.           endif
  465.           BegLine()
  466.           sstring = GetText(1,CurrLineLen())
  467.           AbandonFile(tid)
  468.           GotoBufferId(oid)
  469.      endif
  470.  
  471. /*
  472.      Set default outfile
  473. */
  474.      if Length(outfile) == 0
  475.           outfile = default_name
  476.      endif
  477.      if SplitPath(outfile, _drive_ | _path_) == ''
  478.           outfile = ramdrive + outfile
  479.      endif
  480.      default_name_2 = SplitPath(outfile, _DRIVE_ | _NAME_) + '.$mp'
  481.      if fileexists(default_name_2)
  482.           erasediskfile(default_name_2)
  483.           editfile(default_name_2)
  484.           abandonfile()
  485.      endif
  486.  
  487. /*
  488.      Place header in outfile.
  489. */
  490.      GotoBufferId(oid)
  491.      AddLine('┌────────────────────────────────────────────────┐')
  492.      AddLine('│ TSGREP v' + v +
  493.              ' ... David Marcus' +
  494.              Format(GetDateStr() + " " + GetTimeStr():18) +" │")
  495.      AddLine('└────────────────────────────────────────────────┘')
  496.      AddLine("         Searchstring: [" + sstring + "]")
  497.      if sgrepmode == cmdline
  498.           AddLine("      Input File Spec: " + GetEnvStr('INFILE'))
  499.      else
  500.           AddLine("      Input File Spec: LOADED FILES + " + infile )
  501.      endif
  502.      AddLine("         File created: " + outfile)
  503.      AddLine("              Options: [" + options + ']')
  504.      AddLine()
  505.      AddLine("              # Files: [")
  506.      AddLine("               # Hits: [")
  507.      AddLine()
  508.      AddLine( SubStr(pad,2,30) + '  Files With Hits   ' +
  509.                       SubStr(pad,2,30) )
  510.      AddLine()
  511.  
  512. /*
  513.      Screen display
  514. */
  515.      Message('')
  516.      Set(Cursor,Off)
  517.      HideMouse()
  518.      PopWinOpen( 08,12, 69,25, 1, '', normal_attr)
  519.      ClrScr()
  520.      Set(Attr, normal_attr)
  521.      VGotoXY(1,2)
  522.      WriteLine(Format('  ┌────────────────────────────────────────────────┐':-54))
  523.      WriteLine(Format('  │ TSGREP v'+v+' ... David Marcus' +
  524.                    Format(GetDateStr() + ' ' + GetTimeStr() :18)  +' │':-54))
  525.      WriteLine(Format('  └────────────────────────────────────────────────┘':-54))
  526.      WriteLine(Format("         Searchstring: [" + sstring + "]": -99))
  527.      if sgrepmode == cmdline
  528.           WriteLine(Format("      Input File Spec: " + GetEnvStr('INFILE'):-99))
  529.      else
  530.           WriteLine(Format("      Input File Spec: LOADED FILES + " + infile:-99 ))
  531.      endif
  532.      WriteLine(Format("         File created: " + outfile:-54))
  533.      WriteLine(Format("              Options: [" + options + ']':-54))
  534.      VGoToXY(1, files_processed_line)
  535.      WriteLine(Format("      Files Completed: [ ]":-54))
  536.      VGoToXY(1, hits_line)
  537.      WriteLine(Format("               # Hits: [ ]":-54))
  538.      Set(Attr,hilite_attr)
  539.      PutLine  ("                            <escape> to abort", 50)
  540.      Set(Attr, normal_attr)
  541.  
  542.      /*
  543.           Process multiple file input (OR single)
  544.      */
  545.  
  546.      multiple_filespecs(infile)
  547.      AbandonFile(GetBufferId('++unnamed++'))
  548.      cid = GetBufferId()           // set 1st file ID
  549.  
  550.      /*
  551.           Perform listfile loading.
  552.      */
  553.      GotoBufferId(cid)
  554.      if Pos('' + list_file_flag + '',CurrFilename())
  555.           LoadFileList()
  556.      endif
  557.      nextfile_if_NOT_excluded()
  558.      cid = GetBufferId()
  559.  
  560. /* --------------------------------------------------------------------------
  561.      MAIN PROCESSING LOOP
  562. */
  563.      repeat
  564.           id = GetBufferId()                 // set id of file being processed
  565.           if Pos(outfile, CurrFilename())
  566.                nextfile_if_NOT_excluded()
  567.                id = GetBufferId()
  568.           endif
  569.           if Pos('' + list_file_flag + '',CurrFilename())
  570.                LoadFileList()
  571.                VGotoXY(1,getting_files_line)
  572.                PutLine("   Getting files from: [" + CurrFilename() + ']' ,42)
  573.  
  574.                GotoBufferId(id)
  575.                if id == cid
  576.                     AbandonFile()
  577.                     nextfile_if_NOT_excluded()
  578.                     id = GetBufferId()
  579.                     cid = id
  580.                else
  581.                     abandonfile()
  582.                     nextfile_if_NOT_excluded()
  583.                     id = GetBufferId()
  584.                endif
  585.           endif
  586.  
  587.           name = CurrFilename()              // get name of file
  588.  
  589.           GotoBufferId(oid)                  // go to output buffer
  590.           GotoColumn(1)
  591.           if Length(name)                    // prevent blank at end
  592.                 InsertText(name_prefix + name + name_suffix)
  593.           endif                              // insert file name
  594.           name_line = CurrLine()             // later, go back to this line
  595.           VGotoXY(1,processing_line)
  596.           PutLine("           Processing: [" + name + ']' ,54)
  597.           CReturn()                          // AND creturn
  598.  
  599.           GotoBufferId(id)                   // goto file being processed
  600.           BegFile()
  601.           while lFind(sstring, options)
  602.                AND CurrLine() <> NumLines()  // stops processing if EOF
  603.                hits = hits + 1
  604.                curr_file_hits = TRUE
  605.                VGotoXY(25,hits_line)
  606.                PutLine(Str(hits)+']',10)
  607.                if write_hits_flag
  608.                     linenumber = CurrLine()       // remember line numer
  609.                     UnMarkBlock()                 // mark found line as block
  610.                     MarkLine()
  611.                     MarkLine()
  612.                     GotoBufferId(oid)             // goto output buffer
  613.                     CopyBlock()                   // copy block
  614.                     BegLine()                     // insert line number
  615.                     if linenumbers               // if so flagged
  616.                          InsertText(Format(linenumber:lndigits) +  ' │ ')
  617.                     endif
  618.                     Down()
  619.                endif
  620.                GotoBufferId(id)              // goto file being processed
  621.                if Pos(one_hit_flag, options)
  622.                     EndFile()
  623.                else
  624.                     Down()                   // AND down
  625.                     BegLine()                // to beginning of next line
  626.                endif
  627.                check_for_abort()
  628.           endwhile
  629.           BegFile()                          // reposition to top of file
  630.           files = files + 1
  631.           VGotoXY(25,files_processed_line)
  632.           PutLine(Str(files)+'] ~' + Str(NumFiles()-2) + ' to go',20)
  633.           NextFile_if_NOT_excluded()
  634.           id = GetBufferId()
  635.  
  636.           if curr_file_hits == FALSE        // if no hits, push file name
  637.                no_hitters_flag = TRUE
  638.                GotoBufferId(oid)            //
  639.                DelLine()                    // get rid of blank line bottom
  640.                GotoLine(name_line)
  641.                InsertLine()
  642.           endif
  643.           curr_file_hits = FALSE
  644.           GotoBufferId(id)
  645.  
  646.           if (GetBufferId() <> cid)          // this processing unloads processed
  647.                PrevFile()                    //   files so don't get VM slows
  648.                if (GetBufferId() <> cid)
  649.                     AbandonFile()
  650.                endif
  651.                GotoBufferId(id)
  652.           endif
  653.           check_for_abort()
  654.      until GetBufferId() == cid
  655.  
  656.      PrevFile()
  657.      AbandonFile()
  658.      VGotoXY(25,files_processed_line)
  659.      PutLine(Str(files)+']',22)              // get rid of 'to go'
  660.  
  661.      end_processing(0)
  662. end
  663.  
  664. /**************************************************************************
  665.           end Processing (including list)
  666.  **************************************************************************/
  667.  
  668. proc end_processing(INTEGER mode)            // mode 1 = interrupted
  669.      GotoBufferId(oid)                       // mode 0 = normal end
  670.      GotoLine(9)  GotoPos(25)
  671.      if mode == 1
  672.           InsertText(Str(files)+']' + name_prefix + 'interrupted' + name_suffix)
  673.      else
  674.           InsertText(Str(files)+']')
  675.      endif
  676.      GotoLine(10) GotoPos(25)
  677.      InsertText(Str(hits)+']')
  678.  
  679.      EndFile()
  680.      DelLine()
  681.      if no_hitters_flag
  682.           repeat
  683.                Up()
  684.           until CurrLineLen() == 0
  685.           CReturn()
  686.           InsertText( SubStr(pad,2,30) + 'Other Files Searched' +
  687.                       SubStr(pad,2,30), _insert_)
  688.      endif
  689.      BegFile()
  690.  
  691.      if NOT SaveAs(outfile, 1)               // ,1 == overlay
  692.           Message('cannot save as ', outfile)
  693.      endif
  694.      if (sgrepmode == cmdline) AND (NOT load_file)
  695.                VGotoXY(3,press_any_key_line)
  696.                PutLine(Format("Press any key to continue": 57), 57)
  697.                Alarm()
  698.                GetKey()
  699.                AbandonEditor()
  700.      else
  701.      PopWinClose()                           // output area
  702.  
  703.           /*
  704.                Get rid of all files other than the output file
  705.           */
  706.           GotoBufferId(oid)
  707.           repeat
  708.                NextFile(_dont_load_)
  709.                if GetBufferId() <> oid
  710.                     AbandonFile()
  711.                     GotoBufferId(oid)
  712.                endif
  713.           until getbufferid() == oid
  714.  
  715.           if sgrepmode == interactive
  716.              reload_files()
  717.                popwinclose()              // fullscreen window
  718.           endif
  719.           /*
  720.                Reset editor
  721.           */
  722.  
  723.           Set(LoadWildFromInside, wild)
  724.           Set(AutoIndent,auto)
  725. //        Set(Break, OFF)
  726.           Set(Insert,im)
  727.           AbandonFile(cid)
  728.           AbandonFile(oid)
  729.           make_other_hit_lists()    // ****
  730.           goto_hit_List(0)
  731.           SetGlobalInt('Bypass_WhenSwitchToFile', FALSE)
  732.           SetGlobalInt('Bypass_WhenFirstEdited', FALSE)
  733.           Set(KillMax,km)
  734.           Set(MsgLevel, Msgs)
  735.           Set(Cursor,On)
  736.           ShowMouse()
  737.  
  738.      endif
  739.      done_executed_once = TRUE
  740.      UpdateDisplay()
  741.      hilite()
  742.      Message('Alt+H for help.')
  743. end
  744.  
  745. proc goto_hit_List(INTEGER mode)
  746.      EditFile(outfile)
  747.      oid = GetBufferId()
  748.      Enable(hit_file)
  749.      if mode == 0
  750.           BegFile()
  751.           linenumber = 1
  752.           col = 1
  753.           if lFind(name_prefix,'')
  754.                first_file_line = CurrLine()
  755.                ScrollToRow( Query(ScreenRows) )
  756.           else
  757.                first_file_line = 12
  758.           endif
  759.      else
  760.           Down()
  761.      endif
  762. end
  763.  
  764. /**************************************************************************
  765.           Load File List
  766.  **************************************************************************/
  767.  
  768. proc loadfileList()           // note: this doesn't load nested files
  769.                               // that is done in main processing
  770.      INTEGER
  771.           cid = GetBufferId()
  772.      EndFile()                // to force processing in the order
  773.      BegLine()                //   files appear in the list file
  774.      repeat
  775.           if CurrLineLen() AND
  776.              Pos(recurse_flag, GetText(1, CurrLineLen()))
  777.                load_recursively( GetText(1, CurrLineLen() -1 ))
  778.                VGotoXY(1,loading_files_line)
  779.                PutLine("   Loading files from: [" + GetText(1, CurrLineLen()) + ']' ,54)
  780.                VGotoXY(1,files_loaded_line)
  781.                PutLine("    Files Inventoried: ["+Str(NumFiles())+"] " ,54)
  782.           elseif CurrLineLen() AND
  783.              (FileExists( GetText(1, CurrLineLen()) ))
  784.                VGotoXY(1,loading_files_line)
  785.                PutLine("   Loading files from: [" + GetText(1, CurrLineLen()) + ']' ,54)
  786.                VGotoXY(1,files_loaded_line)
  787.                PutLine("    Files Inventoried: ["+Str(NumFiles())+"] " ,54)
  788.                EditFile( '-a none.$$$ ' + GetText(1, CurrLineLen()) )
  789.           endif
  790.           GotoBufferId(cid)
  791.           check_for_abort()
  792.      until NOT Up()
  793.      if NumFiles() == 1
  794.           Warn('Cannot locate ANY files')
  795.      endif
  796.      GotoBufferId(cid)
  797.      AbandonFile()
  798.      NextFile()
  799.      VGotoXY(1,files_processed_line)
  800.      PutLine("      Files Completed: [ ]" ,54)
  801.      return()
  802.  
  803. end
  804.  
  805. /**************************************************************************
  806.           Go To Hit
  807.  **************************************************************************/
  808.  
  809. proc GotoHit()
  810.      STRING
  811.           fn[maxfn] = ''
  812. top:
  813.      if GetBufferId() == files_only
  814.           toggle_hits()
  815.      else
  816.           EditFile(outfile)
  817.      endif
  818.      BegLine()
  819.  
  820.      if NumLines() == 2
  821.           Warn('No files matched file spec ....')
  822.           AbandonEditor()
  823.      endif
  824.  
  825.      if CurrLine() < first_file_line            // get to first hit if at top of file
  826.           GotoLine(first_file_line)
  827.      endif
  828.  
  829.      if (CurrLine() < first_file_line)          // get to first hit if at top of file
  830.           OR (currLineLen() == 0)
  831.           GotoLine(first_file_line)
  832.      endif
  833.  
  834.      if (GetText(1,1) == '─') OR (currLineLen() == 0)
  835.           repeat
  836.                Down()
  837.           until GetText(1,Length(name_prefix)) == name_prefix OR
  838.                 (numlines() == CurrLine())
  839.      endif
  840.  
  841.      if numlines() == CurrLine()
  842.           repeat
  843.                Up()
  844.           until GetText(1,Length(name_prefix)) == name_prefix OR
  845.                 (CurrLine() <= first_file_line)
  846.      endif
  847.  
  848.      col = CurrCol()               // get currcol in case search was used
  849.      BegLine()
  850.  
  851.      PushPosition()                // remember line
  852.  
  853.      if GetText(1,Length(name_prefix)) == name_prefix
  854.           linenumber = 0
  855.      else                               // get line number
  856.           linenumber = Val( GetText(1,lndigits))
  857.           while NOT (GetText(1,Length(name_prefix)) == name_prefix)
  858.           AND
  859.                 (CurrLine() >= first_file_line)
  860.                Up()
  861.           endwhile                      // get file name if NOT on it
  862.      endif
  863.  
  864.      fn  =   ( GetText( Length(name_prefix) + 1,
  865.                CurrLineLen() - Length(name_prefix)
  866.                - Length(name_suffix) ) )
  867.      PopPosition()                      // go back to line
  868.      if FileExists(fn)
  869.           EditFile( fn )
  870.           if linenumber
  871.                GotoLine(linenumber)
  872.                GotoColumn(col - 9)      // if isrch was used
  873.           endif
  874.           if write_hits_flag == FALSE   // hits were NOT written
  875.               lFind(sstring, options)   // so goto first
  876.           endif
  877.           Message("'ALT-ENTER' to reselect")
  878.           Disable(hit_file)
  879.           Enable(file)
  880.  
  881.           UpdateDisplay()
  882.           pad = SubStr(pad, 1, 44 - Length(CurrFilename()))
  883.           ScrollToRow(12)
  884.      else
  885.           if Length(fn)
  886.                Warn("Can't find file [" , fn, ']    '  )
  887.                Enable(hit_file)
  888.                Return()
  889.           endif
  890.           goto top
  891.      endif
  892. end
  893.  
  894. /**************************************************************************
  895.           Load Multiple Filespecs
  896.  **************************************************************************/
  897.  
  898. INTEGER proc multiple_filespecs(VAR STRING filespec)
  899.      INTEGER
  900.           files = 0,
  901.           passes = 1
  902.      STRING
  903.           file_to_load[maxspec]='',
  904.           prev_path[maxfn - 14]='',
  905.           prev_drive[2]='',
  906.           orig_file_sep_char[1] = file_sep_char
  907.  
  908.      repeat                             // repeat loop 2x, once for
  909.                                         // unmodified file_sep_char
  910.                                         // once for it set to  ' '
  911.                                         //
  912.      while Pos(file_sep_char, filespec)
  913.           file_to_load = SubStr(
  914.                                 filespec,
  915.                                 1,
  916.                                 Pos(file_sep_char, filespec)-1 )
  917.           /*
  918.              Assign previous filespecs path if none
  919.           */
  920.           if SplitPath(file_to_load, _drive_ | _path_) == ''
  921.                file_to_load = prev_drive + prev_path + file_to_load
  922.           endif
  923.           /*
  924.              Assign previous filespecs drive if none
  925.           */
  926.           if SplitPath(file_to_load , _drive_) == ''
  927.                file_to_load = prev_drive + file_to_load
  928.           endif
  929.  
  930.           prev_drive = SplitPath(file_to_load , _drive_)
  931.           prev_path = SplitPath(file_to_load , _path_)
  932.  
  933.           if Pos(recurse_flag, file_to_load)
  934.                load_recursively(SubStr(file_to_load,
  935.                                         1,
  936.                                         Length(file_to_load)-1))
  937.           else
  938.                if FileExists(file_to_load)
  939.                VGotoXY(1,loading_files_line)
  940.                PutLine("   Loading files from: [" + GetText(1, CurrLineLen()) + ']' ,54)
  941.                VGotoXY(1,files_loaded_line)
  942.                PutLine("    Files Inventoried: ["+Str(NumFiles())+"] " ,54)
  943.  
  944.                     EditFile('-a none.$$$ ' + file_to_load) // edit first spec
  945.                endif
  946.           endif
  947.  
  948.           filespec = SubStr(                 // remove first spec
  949.                          filespec,           // from filespec
  950.                          Pos(file_sep_char, filespec)+1,
  951.                          Length(filespec)
  952.                             )
  953.           files = files + 1
  954.      endwhile
  955.      passes = passes + 1
  956.      file_sep_char = ' '
  957.      until passes == 2
  958.      file_sep_char = orig_file_sep_char      // reset
  959.      /*
  960.         Assign previous filespecs path if none
  961.      */
  962.           if SplitPath(filespec, _drive_ | _path_) == ''
  963.                filespec = prev_drive + prev_path + filespec
  964.           endif
  965.           /*
  966.              Assign previous filespecs drive if none
  967.           */
  968.           if SplitPath(filespec , _drive_) == ''
  969.                filespec = prev_drive + filespec
  970.           endif
  971.  
  972.      if Pos(recurse_flag, filespec)
  973.          load_recursively(SubStr(filespec, 1, Length(filespec)-1))
  974.      else
  975.          EditFile('-a none.$$$  ' + filespec) // edit last spec
  976.      endif
  977.      return(files)
  978. end
  979.  
  980. /**************************************************************************
  981.           Replace Character In STRING
  982.  **************************************************************************/
  983.  
  984.  
  985. /**************************************************************************
  986.           NextFile if NOT Excluded
  987.  **************************************************************************/
  988.  
  989. proc nextfile_if_NOT_excluded()
  990.      STRING
  991.             exclude[255] = GetEnvStr('EXCLUDE')
  992.              + ' .img .exe .com .dll .tif .pcx .$hp .$sc .cif .vgr', // :U:
  993.              fn[8] = '',
  994.              fe[4] = ''
  995.  
  996.      /*
  997.           Goes to next file if NOT on excluded .ext list.
  998.      */
  999.      check_for_abort()
  1000. top:
  1001.      NextFile(_DONT_LOAD_)              // goto bufferid w/o load
  1002.      fn = SplitPath(CurrFilename(),_NAME_)
  1003.      fe = SplitPath(CurrFilename(),_EXT_)
  1004.  
  1005.      if Pos(Format( fe : -4) , exclude)
  1006.           OR ((fn + fe) == 'none.$$$')
  1007.           OR ((fn + fe) == OUTFILE)
  1008.           OR ((fn + fe) == default_name_2)
  1009.           AbandonFile()
  1010.           goto top
  1011.      endif
  1012.      if Length(CurrFilename()) and FileExists((CurrFilename()))
  1013.           EditFile(CurrFilename())      // to load file
  1014.      endif
  1015. end
  1016.  
  1017. /**************************************************************************
  1018.           Load Recursively
  1019.  **************************************************************************/
  1020.  
  1021. proc load_recursively(STRING arg)
  1022.      /*
  1023.           Creates AND loads a list file that has
  1024.           one line for each subdirectory under the
  1025.           specified directory. Each line included the filespec
  1026.           to be searched.
  1027.      */
  1028.      STRING
  1029.           dir[maxspec]     = SplitPath(arg, _DRIVE_ | _PATH_ ),
  1030.           filespec[maxspec]= SplitPath(arg, _NAME_  | _EXT_  ),
  1031.           dir_name[maxspec - 12] = '',
  1032.           dirfile[SizeOf(ramdrive) + 12] = ramdrive + '$temp$.$$$'
  1033.      INTEGER
  1034.            listfile = 0,                     // bufferid for listfile
  1035.            dirlist = 0,                      // bufferid for dir list
  1036.            dir_list_buff = 0,
  1037.            dir_counter = 0
  1038.  
  1039.      if FileExists(arg)                       // if there are files in arg
  1040.          GotoBufferId(listfile)               // add to list file
  1041.          AddLine(arg)
  1042.      endif
  1043.  
  1044.      if listfile
  1045.           AbandonFile(listfile)
  1046.      endif
  1047.      if dirlist
  1048.           AbandonFile(dirlist)
  1049.      endif
  1050.      listfile = CreateTempBuffer()     // bufferid for listfile
  1051.      dirlist = CreateTempBuffer()      // bufferid for dir list
  1052.  
  1053.      dir_name = dir
  1054.      VGotoXY(1,getting_dirs_line)
  1055.      PutLine("   Finding Dirs Under: [" + dir + ']' ,54)
  1056.      VGotoXY(1,dirs_found_line)
  1057.      PutLine("           Dirs Found: [ ]" ,54)
  1058.      EndFile()                // to force processing in the order
  1059.  
  1060. top:
  1061.      /*
  1062.           Create buffer to hold a directory AND get
  1063.           it in there.
  1064.      */
  1065.      if dir_list_buff
  1066.           AbandonFile(dir_list_buff)
  1067.      endif
  1068.      dir_list_buff = CreateTempBuffer()
  1069.  
  1070.      DOS('dir ' + dir + dir_spec + ' > ' + dirfile, _dont_clear_ )
  1071.      GotoXY(1,1)                   // avoids some DOS pita-ness
  1072.      insertfile (dirfile)
  1073.  
  1074.      VGotoXY(1,getting_dirs_line)
  1075.      PutLine("   Finding Dirs Under: [" + dir + ']' ,54)
  1076.      repeat                        // for each line in directory
  1077.           check_for_abort()
  1078.           BegLine()
  1079.           while (                  // delete lines we don't want
  1080.                  CurrChar() == Asc(' ') OR   //
  1081.                  CurrChar() == Asc('.') OR
  1082.                  CurrLineLen() == 0
  1083.                 )
  1084.                 AND
  1085.                 (NumLines() <> CurrLine())
  1086.                DelLine()
  1087.           endwhile
  1088.  
  1089.           line = GetText(1, CurrLineLen())   // work with line we do
  1090.  
  1091.           if NOT Pos('<DIR>', line)          // if NOT a directory
  1092.                DelLine()                     // delete it
  1093.           else
  1094.                dir_counter = dir_counter + 1
  1095.                VGotoXY(1,dirs_found_line)
  1096.                PutLine("           Dirs Found: ["+Str(dir_counter)+"] "
  1097.                          + dir_name ,54)
  1098.                dir_name = dir + GetText(1,Pos(' ', line)-1)
  1099.                if GetText(12,1) <> ' '       // check for .nnn dir name
  1100.                     dir_name = dir_name + '.' + GetText(10,3)
  1101.                elseif GetText(11,1) <> ' '   // check for .nn dir name
  1102.                     dir_name = dir_name + '.' + GetText(10,2)
  1103.                elseif GetText(10,1) <> ' '   // check for .n dir name
  1104.                     dir_name = dir_name + '.' + GetText(10,1)
  1105.                endif
  1106.  
  1107.                GotoBufferId(dirlist)         // add to the list of dirs
  1108.                AddLine(dir_name)             // to process
  1109.  
  1110.                if FileExists(dir_name + '\' + filespec)
  1111.                     GotoBufferId(listfile)        // add to list file
  1112.                     AddLine(dir_name + '\' + filespec)
  1113.                endif
  1114.  
  1115.                GotoBufferId(dir_list_buff)
  1116.           endif
  1117.      until NOT  Down()
  1118.      AbandonFile()                                // abandon dir_list_buff
  1119.  
  1120.      /*
  1121.           repeat for any directories left
  1122.           to process
  1123.      */
  1124.      GotoBufferId(dirlist)
  1125.      BegFile()
  1126.      if NumLines() AND CurrLineLen()
  1127.           dir = GetText(1,CurrLineLen()) + '\'    // set next dir to process
  1128.           DelLine()                               // delete it from list
  1129.           goto top                                // loop around
  1130.      endif
  1131.      AbandonFile(dirlist)
  1132.      GotoBufferId(listfile)                       // mark all of listfile
  1133.      BegFile()
  1134.      MarkLine()
  1135.      EndFile()
  1136.      MarkLine()
  1137.      if FileExists('' + list_file_flag + '')
  1138.           EraseDiskFile('' + list_file_flag + '')
  1139.      endif
  1140.      EditFile('' + list_file_flag + '')                                // copy to an @file file
  1141.      CopyBlock()                                  // which will be processed
  1142.                                                   // AND abandoned by TSGREP
  1143.      AbandonFile(listfile)
  1144.      EraseDiskFile(dirfile)
  1145.      Message('')
  1146. end
  1147.  
  1148. /**************************************************************************
  1149.           Process "AND" in Searchstring
  1150.  **************************************************************************/
  1151.  
  1152. proc process_AND()
  1153.      STRING
  1154.           part1[maxspec] = '',
  1155.           part2[maxspec] = ''
  1156.  
  1157.      part1 = SubStr(sstring, 1, Pos(AND_operator,sstring) - 1)
  1158.      part2 = SubStr(sstring,    Pos(AND_operator,sstring) + Length(AND_operator), Length(sstring))
  1159.      sstring = '{'+ part1 + '.*' + part2 + '}|{' +
  1160.                     part2 + '.*' + part1 + '}'
  1161. end
  1162.  
  1163. /**************************************************************************
  1164.           Check for Abort
  1165.  **************************************************************************/
  1166.  
  1167. proc check_for_abort()
  1168.      if KeyPressed() AND GetKey() == <escape>
  1169.           PushKey(<enter>)              // bypasses 'press any key'
  1170.           end_processing(1)
  1171.           halt                          // Avoid going back to where
  1172.      endif                              // check_for_abort was called
  1173. end
  1174.  
  1175. /**************************************************************************
  1176.           Create Files-Only List AND Create Backup Complete List
  1177.  **************************************************************************/
  1178.  
  1179. proc make_other_hit_lists()
  1180.      msgs = Set(MsgLevel,_warnings_only_)
  1181.      if copy_of_list
  1182.           AbandonFile(copy_of_list)
  1183.      endif
  1184.      copy_of_list = CreateTempBuffer()
  1185.      InsertFile(outfile)
  1186.      if files_only
  1187.           AbandonFile(files_only)
  1188.      endif
  1189.      files_only = CreateTempBuffer()
  1190.      message(default_name_2)
  1191.      SaveAs(default_name_2,1)
  1192.      EditFile(default_name_2)
  1193.      AbandonFile(files_only)
  1194.      files_only = GetBufferId()
  1195.      InsertFile(outfile)
  1196.      Set(KillMax,0)
  1197.      repeat
  1198.           if ( Val(GetText(1, lndigits)))
  1199.                DelLine()
  1200.           else
  1201.                Down()
  1202.           endif
  1203.      until NumLines() == CurrLine()
  1204.      Set(KillMax,km)
  1205.      ForceChanged(FALSE)
  1206.      GotoBufferId(oid)
  1207.      PopBlock()
  1208.      Set(MsgLevel,msgs)
  1209. end
  1210.  
  1211. /**************************************************************************
  1212.           Setup Stuff for Interactive Operation
  1213. **************************************************************************/
  1214. proc interactive_setUp()
  1215.  
  1216.      cid = GetBufferID()
  1217.           repeat
  1218.           if ischanged()  and query_saves
  1219.                updatedisplay()
  1220.                case YesNo( 'Save changes?')
  1221.                     when 0, 2, 3           // Escape OR Cancel
  1222.                          if GetBufferID() == cid    // reset cid
  1223.                               prevfile()
  1224.                               cid = GetBufferID()
  1225.                               nextfile()
  1226.                          endif
  1227.                          name = CurrFileName()
  1228.                          linenumber = CurrLine()
  1229.                          Message('Reloading ' + name)
  1230.                          AbandonFile()
  1231.                          editfile(name)
  1232.                          GoToLine(linenumber)
  1233.                          UpDateDisplay(_STATUSLINE_REFRESH_)
  1234.                    when 1                   // Yes
  1235.                          SaveFile()      //
  1236.                    endcase
  1237.           else
  1238.                SaveFile()
  1239.           endif
  1240.           NextFile()
  1241.           until cid == GetBufferID()
  1242.  
  1243.  
  1244.     PopWinOpen( 01,01, Query(ScreenCols), Query(ScreenRows), 0, '',
  1245.        Query(OtherWinBorderAttr))    // to blank screen
  1246.     ClrScr()
  1247.  
  1248.      if NOT ask_input()
  1249.           AbandonFile(cfid)
  1250.           PopWinClose()            // full screen window
  1251.           AbandonFile(GetBufferId('++unnamed++'))
  1252.           halt
  1253.      endif
  1254.  
  1255.      msgs = Set(MsgLevel,_NONE_)
  1256.      if GetBufferId(outfile)
  1257.           AbandonFile(GetBufferId(outfile))
  1258.      endif
  1259.      Set(MsgLevel,msgs)
  1260.  
  1261.  
  1262.  
  1263.      if infile == ''               // seems to required
  1264.           infile = 'none.$$$'           // else a file is dropped!
  1265.      endif
  1266.  
  1267.      /*
  1268.           List currently-loaded files for later reload
  1269.      */
  1270.      PrevFile(_DONT_LOAD_)                   // currently-loaded files
  1271.      NextFile(_DONT_LOAD_)                   // start from a file
  1272.      cid = GetBufferId()
  1273.  
  1274.      if cfid
  1275.           AbandonFile(cfid)
  1276.      endif
  1277.      cfid = CreateTempBuffer()               // buffer to hold list
  1278.  
  1279.      GotoBufferId(cid)
  1280.      repeat
  1281.           id = GetBufferId()
  1282.           name = CurrFilename()              // file name
  1283.           isloaded = iif(NumLines(), 1, 0)   // whether to reload
  1284.           linenumber = CurrLine()            // line to which to go
  1285.           GotoBufferId(cfid)
  1286.           AddLine(Format(name : -maxfn) +
  1287.                   Format(isloaded) +
  1288.                   Str(linenumber) )
  1289.           GotoBufferId(id)
  1290.           NextFile(_DONT_LOAD_)
  1291.      until GetBufferID() == cid
  1292. end
  1293.  
  1294. /**************************************************************************
  1295.           Reload Files (Interactive Mode)
  1296.  **************************************************************************/
  1297. proc reload_files()
  1298.      INTEGER count = 0
  1299.      cid = GetBufferId()
  1300.      if NOT cfid                   // in case current file list NOT built
  1301.           return()
  1302.      endif
  1303.      GotoBufferId(cfid)
  1304.      BegFile()
  1305.      repeat
  1306.           count = count + 1
  1307.           GotoBufferId(cfid)
  1308.           if GetText(1,11) == '++unnamed++'
  1309.                                              // do nothing
  1310.           elseif GetText(maxfn + 1, 1) == '1'
  1311.                EditFile(SubStr(
  1312.                                 GetText(1,maxfn), 1, Pos(' ', GetText(1,maxfn))
  1313.                               ) +
  1314.                          '-n' + GetText(maxfn + 2, lndigits)
  1315.                        )
  1316.           else
  1317.                EditFile(outfile + ' ' + GetText(1,maxfn))
  1318.           endif
  1319.           GotoBufferId(cfid)
  1320.      until NOT Down()
  1321.      AbandonFile(cfid)
  1322. end
  1323.  
  1324. /**************************************************************************
  1325.           Toggle From Showing Detail to NOT Showing It
  1326.  **************************************************************************/
  1327.  
  1328. proc toggle_hits()
  1329.      INTEGER
  1330.           row = CurrRow()
  1331.      if GetBufferId() == oid
  1332.           PushPosition()
  1333.           EndLine()
  1334.           lFind(name_prefix, '^b')
  1335.           row = CurrRow()
  1336.           line=GetText(1,CurrLineLen())
  1337.           PopPosition()
  1338.           GotoBufferId(files_only)
  1339.           BegFile()
  1340.           lFind(line,'^')
  1341.           ScrollToRow(row)
  1342.      elseif getbufferid() == files_only
  1343.           EndLine()
  1344.           lFind(name_prefix, '^b')
  1345.           line=GetText(1,CurrLineLen())
  1346.           ForceChanged(FALSE)
  1347.           GotoBufferId(oid)
  1348.           BegFile()
  1349.           lFind(line,'^')
  1350.           ScrollToRow(row)
  1351.      endif
  1352.      UpdateDisplay()
  1353.      hilite()
  1354. end
  1355. /**************************************************************************
  1356.           Remove File From Hit List
  1357.  **************************************************************************/
  1358.  
  1359. proc remove_file_from_hit_List()
  1360.      INTEGER
  1361.           startbuffer = GetBufferId(),
  1362.           counter = 0
  1363.      Set(KillMax, 0)
  1364.      PushBlock()
  1365.      PushPosition()
  1366.      UnMarkBlock()
  1367.      EndLine()
  1368.      if startbuffer == files_only
  1369.           if GetText(1,Length(name_prefix)) <> name_prefix
  1370.                Warn('NOT on file name')
  1371.                   return()
  1372.           endif
  1373.           line = GetText(1,80)
  1374.           DelLine()
  1375.           ForceChanged(FALSE)
  1376.           GotoBufferId(oid)
  1377.           begfile()
  1378.           if NOT lFind(line, '^')
  1379.                Warn("can't find ", line)
  1380.                Set(KillMax, km)
  1381.                return()
  1382.           endif
  1383.      endif
  1384.  
  1385.      name_prefix_re = ''                // build an escaped reg_exp version
  1386.      repeat                             // of name_prefix (because RE is used)
  1387.      counter = counter + 1              // in alt-p and alt-n)
  1388.           if Pos(name_prefix[counter], '.^$\|?[]*+@#{}')
  1389.                name_prefix_re = name_prefix_re + '\'
  1390.           endif
  1391.           name_prefix_re = name_prefix_re + name_prefix[counter]
  1392.      until counter == Length(name_prefix)
  1393.  
  1394.      if (GetText(1,Length(name_prefix)) == name_prefix) AND Down() AND
  1395.         (GetText(1,Length(name_prefix)) == name_prefix) OR
  1396.         (NumLines() <= (CurrLine() + 1))
  1397.           Up()
  1398.           line = GetText(1,80)
  1399.           DelLine()
  1400.           PopBlock()
  1401.      elseif lFind('{'+ name_prefix_re + '}|{─}', '^x') AND
  1402.         Up() AND
  1403.         MarkLine() AND
  1404.         lFind(name_prefix, '^b') AND
  1405.         MarkLine()
  1406.           GotoBlockBegin()
  1407.           line = GetText(1,80)
  1408.           GotoBlockEnd()
  1409.           Down()
  1410.           DelBlock()
  1411.      endif
  1412.      PopBlock()
  1413.  
  1414.      if startbuffer == oid
  1415.           GotoBufferId(files_only)
  1416.           if lFind(line, '^')
  1417.                DelLine()
  1418.                ForceChanged(FALSE)
  1419.           endif
  1420.      endif
  1421.      PopPosition()
  1422.      BegLine()
  1423.      Set(KillMax, km)
  1424.      ForceChanged(FALSE)
  1425.      UpdateDisplay()
  1426.      hilite()
  1427. end
  1428.  
  1429. /**************************************************************************
  1430.           Undo All "Remove File From Hit List"
  1431.  **************************************************************************/
  1432.  
  1433. proc undo_all_removes()
  1434.      INTEGER
  1435.           row = 0
  1436.      PushBlock()
  1437.      UnMarkBlock()
  1438.      GotoBufferId(oid)
  1439.      line = GetText(1,80)
  1440.      row = CurrRow()
  1441.      BegFile()      MarkLine()
  1442.      EndFile()      MarkLine()
  1443.      Set(KillMax,0)
  1444.      DelBlock()
  1445.      Set(KillMax,km)
  1446.      GotoBufferId(copy_of_list)
  1447.      BegFile() MarkLine()
  1448.      EndFile() MarkLine()
  1449.      GotoBufferId(oid)
  1450.      CopyBlock()
  1451.      PopBlock()
  1452.      lFind(line, '^')
  1453.      PushPosition()
  1454.      AbandonFile(files_only)
  1455.      AbandonFile(copy_of_list)
  1456.      make_other_hit_lists()
  1457.      PopPosition()
  1458.      ScrollToRow(row)
  1459.      UpdateDisplay()
  1460.      hilite()
  1461. end
  1462.  
  1463. proc hilite()
  1464.      UpdateDisplay()                         // seems needed twice sometimes
  1465.      UpdateDisplay()
  1466.      if PosLastNonWhite() -  CurrPos() + 1
  1467.         PutAttr(Query(HiLiteAttr), PosLastNonWhite() -  CurrPos() + 1)
  1468.      endif
  1469. end
  1470.  
  1471. /**************************************************************************
  1472.           Ask for Input
  1473.  **************************************************************************/
  1474. INTEGER proc ask_input()
  1475.      PopWinOpen( 01,05, Query(ScreenCols), Query(ScreenRows), 2, '',
  1476.           Query(OtherWinBorderAttr))              // help screen
  1477.      Set(y1,1)
  1478.      WriteLine('Your search STRING may be any TSE search string. However:')
  1479.      WriteLine('  * You may use  ' + or_operator + ' instead of |.')
  1480.      WriteLine('  * You may use ' + space_char + ' instead of space.')
  1481.      WriteLine('  * You may use ' + eq_char + ' for =.')
  1482.      WriteLine('  * You may use ' + less_than + ' for <.')
  1483.      WriteLine('  * You may use ' + greater_than + ' for >.')
  1484.      WriteLine('(These required for command line operation.)')
  1485.      WriteLine('')
  1486.      WriteLine('If ' + or_operator + ' is not surrounded by }{, TSGREP will supply the braces. So,')
  1487.      WriteLine('"menu' + or_operator + 'proc' + or_operator + 'keydef" gets turned into "{menu}|{proc}|{keydef}".')
  1488.      WriteLine('All braces you do supply are honored.')
  1489.      WriteLine('')
  1490.      WriteLine('Use '+ and_operator + ' to mean "and" in the search string. May be only used')
  1491.      WriteLine('once in the string. Order is not important; a'+ and_operator + 'b means')
  1492.      WriteLine('(a.*b) OR (b.*a) ... and that is exactly how it is implemented.')
  1493.      WriteLine('')
  1494.      WriteLine('If combining OR with AND, use braces to surround the terms')
  1495.      WriteLine('being ORd. For instance: "sort'+ and_operator + 'b{search' + or_operator + 'subtotal}".')
  1496.      if NOT
  1497.          Ask(Format("Search string?" : - Query(ScreenCols)),
  1498.                sstring, sstring_hist_buff)
  1499.           PopWinCLose()                      // help screen
  1500.           return(FALSE)
  1501.      endif
  1502.  
  1503.      ClrScr()
  1504.  
  1505.      WriteLine('Files currently in the ring are always searched. Files specified at this')
  1506.      WriteLine('prompt are searched additionally. The original ring is restored after the')
  1507.      WriteLine('searches; no additional files are left loaded.')
  1508.      WriteLine('')
  1509.      WriteLine('Use ' + file_sep_char + ' as a separator for multiple files, as in "*.q' + file_sep_char + '*.inc' + file_sep_char + 'q:c*.??c".')
  1510.      WriteLine('If you use ' + file_sep_char + ' and  a filespec has no drive and path, the ones for the')
  1511.      WriteLine('preceding filespec are applied to it. For instance:')
  1512.      WriteLine('     i:\usr\*.txt' + file_sep_char + '*.doc' + file_sep_char + 'c:\*.txt' + file_sep_char + '*.doc')
  1513.      WriteLine('is processed as')
  1514.      WriteLine('     i:\usr\*.txt' + file_sep_char + 'i:\usr\*.doc' + file_sep_char + 'c:\*.txt' + file_sep_char + 'c:\*.doc')
  1515.      WriteLine('')
  1516.      WriteLine('Files with "' + list_file_flag + '" in any position of the name are treated as list files.')
  1517.      WriteLine('List files may contain specific file names, wildcarded filespecs, and')
  1518.      WriteLine('additional listfile names. Place one spec per line, starting each in ')
  1519.      WriteLine('column 1. You can use multiple list files on the command line or ')
  1520.      WriteLine('combine them with other filespecs.')
  1521.      WriteLine('')
  1522.      WriteLine('Add ' + recurse_flag + ' to the end of a filespec to have TSGREP process')
  1523.      Write    ('matching files in all subdirectories of the specified one.')
  1524.  
  1525.      Set(y1,1)
  1526.      if NOT
  1527.          Ask(Format("File(s) OR filespec to search?" : - Query(ScreenCols)),
  1528.                infile, infile_hist_buff)
  1529.           PopWinCLose()                      // help screen
  1530.           return(FALSE)
  1531.      endif
  1532.  
  1533.      ClrScr()
  1534.      WriteLine('Options may be include any TSE search option except "b", "g" AND "+".')
  1535.      WriteLine('TSE options you can use include i x w ^ AND $.')
  1536.      WriteLine('')
  1537.      WriteLine('Default options are "i". If any of these strings are contained in the')
  1538.      WriteLine('search string, "x" is automatically added to the options unless "' + no_re_flag + '" is')
  1539.      WriteLine('is used as an option: ' + or_operator + ' .* [ '+ and_operator + '.')
  1540.      WriteLine('')
  1541.      WriteLine('Use ' + no_line_numbers + ' in options to suppress line numbers.')
  1542.      WriteLine('    ' + one_hit_flag + ' to stop searching each file after 1 hit found.')
  1543.      WriteLine('    ' + dont_decode_spacechar + ' to force reading of "' + space_char + '" in the search STRING as underscores')
  1544.      WriteLine('       rather than spaces.')
  1545.      WriteLine('    ' + dont_write_hits + ' to NOT write lines with hits to outfile; only list file names.')
  1546.      WriteLine('    ' + no_re_flag + ' to overide automatic kick in of regular expression.')
  1547.      WriteLine('    ' + dont_load_outfile + ' to not have the output file loaded.')
  1548.  
  1549.      Set(y1,1)
  1550.      if NOT
  1551.          Ask(Format('Search options?': - Query(ScreenCols)),
  1552.                options, options_hist_buff)
  1553.           PopWinCLose()                      // help screen
  1554.           return(FALSE)
  1555.      endif
  1556.  
  1557.      ClrScr()
  1558.      WriteLine('Outfile is optional; the default is ' + default_name+ '.')
  1559.      Set(y1,1)
  1560.      if NOT
  1561.          Ask(Format('File to create?': - Query(ScreenCols)),
  1562.                outfile, outfile_hist_buff)
  1563.           PopWinClose()                      // help window
  1564.           return(FALSE)
  1565.      else
  1566.           PopWinClose()                       // help window
  1567.           return(TRUE)
  1568.      endif
  1569.      return(TRUE)
  1570. end
  1571.  
  1572. /**************************************************************************
  1573.           Unload TSGREP
  1574.  **************************************************************************/
  1575. proc unload()
  1576.      cid = GetBufferID()
  1577.      AbandonFile(copy_of_list)
  1578.      AbandonFile(files_only)
  1579.      if EditFile(default_name_2)
  1580.           KillFile()
  1581.           AbandonFile()
  1582.      endif
  1583.      gotobufferid(oid)
  1584.      updatedisplay()
  1585.      QuitFile()
  1586.      GotoBufferID(cid)
  1587.      PurgeMacro('sgrep')
  1588.      Message("TSGREP purged.")
  1589.      Alarm()
  1590. end
  1591.  
  1592. /**************************************************************************
  1593.           Keystroke Help
  1594.  **************************************************************************/
  1595.  
  1596. Help keystrokes
  1597.      title = 'Keystrokes for TSGREP:'
  1598.      width = 78
  1599.      height = 17
  1600.      x = 1 y = 2
  1601. ''
  1602. '■ While you are in the file listing hits:'
  1603. ''
  1604. '     <alt F>            Toggle showing lines with hits or only filenames'
  1605. '     <alt N>, <alt P>   Go to next/prev file in listing'
  1606. '     <alt R>, <alt U>   Remove the entries for a file/undo all removes'
  1607. '     <alt enter>        Edit file AND go to line the cursor is on'
  1608. '     <alt h>            Pop up this help window.'
  1609. '     <alt ->            Unload TSGREP. (All keys revert to normal use.)'
  1610. ''
  1611. '■ While editing one of the files listed'
  1612. ''
  1613. '     <alt N>, <alt P>   Goto next/prev hit in this file'
  1614. '     <alt enter>        Go back to the file listing hits'
  1615. '     <alt h>            Pop up this help window.'
  1616. '     <alt ->            Unload TSGREP. (All keys revert to normal use.)'
  1617. ''
  1618. '                     Press any key when you have memorized this screen.'
  1619. end
  1620.  
  1621. proc keystroke_help()
  1622.      Message('Press any key to continue')
  1623.      showhelp(keystrokes)
  1624.      updatedisplay()
  1625. end
  1626.